﻿// <copyright>
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
// System.ServiceModel.Internals\System\Runtime\AsyncEventArgs.cs

#if DESKTOPCLR
using System;
//using System.Diagnostics;
//using CuteAnt.Diagnostics;

namespace CuteAnt.Runtime
{
  [Fx.Tag.SynchronizationPrimitive(Fx.Tag.BlocksUsing.NonBlocking, SupportsAsync = true, ReleaseMethod = "Complete")]
  public abstract class AsyncEventArgs : IAsyncEventArgs
  {
//#if DEBUG
//    StackTrace startStack;
//    StackTrace completeStack;
//#endif
    OperationState state;
    object asyncState;
    AsyncEventArgsCallback callback;
    Exception exception;

    public Exception Exception
    {
      get { return this.exception; }
    }

    public object AsyncState
    {
      get { return this.asyncState; }
    }

    OperationState State
    {
      set
      {
        switch (value)
        {
          case OperationState.PendingCompletion:
            if (this.state == OperationState.PendingCompletion)
            {
              throw Fx.Exception.AsError(new InvalidOperationException(InternalSR.AsyncEventArgsCompletionPending(GetType())));
            }
            // ## 苦竹 屏蔽 ##
            //#if DEBUG
            //            if (!Fx.FastDebug)
            //            {
            //              this.startStack = new StackTrace();
            //            }
            //#endif
            break;
          case OperationState.CompletedAsynchronously:
          case OperationState.CompletedSynchronously:
            if (this.state != OperationState.PendingCompletion)
            {
              throw Fx.Exception.AsError(new InvalidOperationException(InternalSR.AsyncEventArgsCompletedTwice(GetType())));
            }
            // ## 苦竹 屏蔽 ##
            //#if DEBUG
            //            if (!Fx.FastDebug)
            //            {
            //              this.completeStack = new StackTrace();
            //            }
            //#endif
            break;
        }

        this.state = value;
      }
    }

    public void Complete(bool completedSynchronously)
    {
      this.Complete(completedSynchronously, null);
    }

    public virtual void Complete(bool completedSynchronously, Exception exception)
    {
      // The callback will be invoked only if completedSynchronously is false.
      // It is the responsibility of the caller or callback to throw the exception.
      this.exception = exception;
      if (completedSynchronously)
      {
        this.State = OperationState.CompletedSynchronously;
      }
      else
      {
        this.State = OperationState.CompletedAsynchronously;
        this.callback(this);
      }
    }

    protected void SetAsyncState(AsyncEventArgsCallback callback, object state)
    {
      if (callback == null)
      {
        throw Fx.Exception.ArgumentNull("callback");
      }

      this.State = OperationState.PendingCompletion;
      this.asyncState = state;
      this.callback = callback;
    }

    enum OperationState
    {
      Created,
      PendingCompletion,
      CompletedSynchronously,
      CompletedAsynchronously,
    }
  }

  public class AsyncEventArgs<TArgument> : AsyncEventArgs
  {
    public TArgument Arguments
    {
      get;
      private set;
    }

    public virtual void Set(AsyncEventArgsCallback callback, TArgument arguments, object state)
    {
      this.SetAsyncState(callback, state);
      this.Arguments = arguments;
    }
  }

  public class AsyncEventArgs<TArgument, TResult> : AsyncEventArgs<TArgument>
  {
    public TResult Result { get; set; }
  }
}
#endif
